/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef XMINSTRUMENT__H
#define XMINSTRUMENT__H

#include <string>
#include <vector>
#include <NoCopy.h>
#include "Envelope.h"
#include <resource/Resource.h>

class XMInstrument : private Nocopy
{
public:
	class XMSample : private Nocopy
	{
	public:
		unsigned sample_length;
		unsigned loop_start;
		unsigned loop_length;
		unsigned char volume;
		signed char fine_tune; //(signed byte -16..+15)
		unsigned char type;
		unsigned char panning;
		signed char relative_note; //(signed byte)
		std::string name; //Sample name
		void * data;
		std::string instrument_name;

		explicit XMSample( resource::Resource * resource, const std::string & instrument_name );
		~XMSample();

		void read_sample_data( resource::Resource * resource );

		void * get_data( int sample_start, int samples )const
		{
			return ((char *)data) + sample_start * get_sample_size();
		}

		int get_sample_size()const
		{
			if( type & 0x10 )
				return 2;

			return 1;
		}

		int get_length()const
		{
			return sample_length;
		}
	};

private:
	std::string name;
	std::vector< XMSample * > samples;
	std::vector< unsigned char > sample_number; //Number of sample for each note

	Envelope volume_envelope;
	Envelope panning_envelope;

	char vibrato_type;
	char vibrato_sweep;
	char vibrato_depth;
	char vibrato_rate;
	short volume_fadeout;
public:
	explicit XMInstrument( resource::Resource * resource );
	~XMInstrument();

	int get_volume_fade()const
	{
		return volume_fadeout;
	}
	const Envelope & get_volume_envelope()const
	{
		return volume_envelope;
	}
	const Envelope & get_panning_envelope()const
	{
		return panning_envelope;
	}
	const XMSample * get_sample( int note )const
	{
		if ( note >= (int)sample_number.size() )
			return 0;

		return samples[ sample_number[ note ] ];
	}
};

#endif